; ********宏定义区********
; 定义PWM变量寄存器
PWM_VAR EQU R7
PWM_NUM_RES EQU 20  ; 定义PWM的分辨率，20表示一个PWM周期分成20份，即占空比精度为5%
PWM_OUT_PORT EQU P1.7
; 定义重装载定时器初始值的宏
; 如何计算TIME_US的值：
; 假设要求PWM的周期为15000us，即15ms，分辨率为r=20，那么频率为f=1s/15ms=(1000/15)Hz=66.7Hz
; 那么定时器的中断频率为f'=f*r=66.7*20=1334Hz
; 定时器的中断周期为1/1334s=750us
; 即TIME_US的值为750
RELOAD_TIM0 MACRO TIME_US
MOV TH0, #(65535-TIME_US)/256
MOV TL0, #(65535-TIME_US) MOD 256
ENDM

; ********定时器中断处理函数********
TIM0_IT_Handler:
PUSH ACC
RELOAD_TIM0 750      ; 重装载定时器
INC PWM_VAR          ; PWM变量自增
MOV A, PWM_VAR       ; 判断是否到达最大值  
CJNE A, #PWM_NUM_RES, INT0_END
MOV PWM_VAR, 0       ; 到达最大值，清零变量
INT0_END:            ; 未到达最大值，啥都不做
POP ACC
RETI

; ********主程序内容********
START:
MOV SP, #30H    ;将栈指针移至栈段
; 配置定时器
MOV TMOD, #01H
RELOAD_TIM0 750
; 开中断
SETB EA
SETB ET0
; 初始化变量
MOV PWM_VAR, #0
; 启动定时器
SETB TR0

; 主循环
MAIN_LOOP:
; PWM_COMPARE_START
MOV A, PWM_VAR
JZ RASING
MOV A, PWM_VAR
SUBB A, #10     ; 这里参数2的值决定了PWM的占空比，参数2=占空比*分辨率，结果根据需要向上或向下取整
JZ FALLING
SJMP PWM_CMP_END
RASING:         ; 产生上升沿
SETB PWM_OUT_PORT
SJMP PWM_CMP_END

FALLING:        ; 产生下降沿
CLR PWM_OUT_PORT
SJMP PWM_CMP_END

PWM_CMP_END:
; PWM_COMPARE_END
LJMP MAIN_LOOP
SJMP $